package com.hmdp.interceptor;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.hmdp.dto.Result;
import com.hmdp.dto.UserDTO;
import com.hmdp.utils.RedisConstants;
import com.hmdp.utils.ThreadLocalUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.Duration;
import java.util.Map;

@Component
@RequiredArgsConstructor
@Slf4j
public class UserRefreshInterceptor implements HandlerInterceptor {
    @Resource
    private RedisTemplate redisTemplate;//注入redistemplate对象操作redis数据库
    @Resource
    private StringRedisTemplate stringRedisTemplate;//注入StringRedisTemplate对象操作redis数据库

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("在访问Controller的功能接口方法之前执行");

       /* //2.如果session中存在用户信息,则放行并且保存至线程域变量ThreadLocal中,否则拦截
        //获取HttpSession对象
        HttpSession session = request.getSession();
        //获取用户信息
        Object user = session.getAttribute("user");
        //判断用户信息是否存在*/

        //从请求头中取出token(这个token就是redis中用户信息的key)
        String token = request.getHeader("authorization");
        //判断token是否为空
        if (StrUtil.isBlank(token)) {
            log.info("不存在用户登入令牌");
            return true;// 放行到登入拦截器进行用户校验
        }
       /* //从redis中获取用户信息
        String currentLoginUserStr = (String) redisTemplate.opsForValue().get(RedisConstants.LOGIN_USER_KEY + ":" + token);
        //json字符串转换为User对象
        User user = JSONUtil.toBean(currentLoginUserStr, User.class);*/
        Map<Object, Object> userMap = stringRedisTemplate.opsForHash().entries(RedisConstants.LOGIN_USER_KEY + ":" + token);
        // 3.判断用户是否存在
        if (userMap.isEmpty()) {
            log.info("redis中没有该用户缓存");
            return true;//放行到登入拦截器进行用户校验
        }
        // 5.将查询到的hash数据转为UserDTO
        UserDTO userDTO =  BeanUtil.mapToBean(userMap, UserDTO.class, true, CopyOptions.create().setIgnoreNullValue(true));
        //判断用户信息是否存在
        if (userDTO == null) {
            log.info("redis中没有该用户缓存");
            return true;// 放行到登入拦截器进行用户校验
        }
        //将用户信息保存至线程域变量ThreadLocal中
        /*UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);*/
        ThreadLocalUtil.set(userDTO);//将用户信息转换为User对象并保存至ThreadLocal中
        //刷新token的有效期
        //设置TTL有效期
        redisTemplate.expire(RedisConstants.LOGIN_USER_KEY + ":" + token, Duration.ofSeconds(RedisConstants.LOGIN_USER_TTL));
        return true;// 放行
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
       //前端视图渲染完毕后执行
        //清除线程区域变量中的用户信息
        ThreadLocalUtil.remove();
    }
}
